﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using EZhouReportConvertTool.Model;
using Microsoft.Win32;
using MiniExcelLibs;
using MiniExcelLibs.Csv;
using MiniExcelLibs.OpenXml;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Forms;
using static EZhouReportConvertTool.MainWindowsViewModel;
using static System.Net.WebRequestMethods;
using File = System.IO.File;
using MessageBox = System.Windows.MessageBox;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;

namespace EZhouReportConvertTool
{
    public partial class MainWindowsViewModel : ObservableObject
    {
        Config _config;

        [ObservableProperty]
        private ObservableCollection<BinMapViewModelItem> _binMapViewModelViewModels;
        [ObservableProperty]
        private BinMapViewModelItem _selectedBinMapViewModelViewModel;
        [ObservableProperty]
        private ObservableCollection<BinMapViewModelItem> _mergeBinMapViewModels;
        [ObservableProperty]
        private BinMapViewModelItem _selectedMergedBinMapViewModel;

        [ObservableProperty]
        private string _mergeTemplateFilePath;
        [ObservableProperty]
        private string _mergeFileInputFilePath;

        [ObservableProperty]
        private string _mergeReportFilePath;
        [ObservableProperty]
        private string _mergeReportFileExportPath;

        partial void OnMergeFileInputFilePathChanged(string value)
        {
            _config.MergeFileInputFilePath = MergeFileInputFilePath;
            _config.Save();
        }

        public MainWindowsViewModel()
        {
            _config = Config.Load();
            TemplatePath = _config.TemplatePath;
            OriginalReportPath = _config.OriginalCSVPath;
            ExportReportPath = _config.ExprotFilePath;
            MergeTemplateFilePath = _config.MergeTemplateFilePath;
            MergeFileInputFilePath = _config.MergeFileInputFilePath;

            BinMapViewModelViewModels = new ObservableCollection<BinMapViewModelItem>(_config.BinMapList.Select(s => new BinMapViewModelItem(s)));
            MergeBinMapViewModels = new ObservableCollection<BinMapViewModelItem>(_config.MergeBinMapList.Select(s => new BinMapViewModelItem(s)));

        }

        partial void OnMergeTemplateFilePathChanged(string value)
        {
            _config.MergeTemplateFilePath = MergeTemplateFilePath;
            _config.Save();
        }

        [RelayCommand]
        private void AddBinMap()
        {
            BinMapViewModelViewModels.Add(new BinMapViewModelItem(new BinMap()));
        }


        [RelayCommand]
        private void DeleteBinMap()
        {
            if (SelectedBinMapViewModelViewModel != null)
            {
                BinMapViewModelViewModels.Remove(SelectedBinMapViewModelViewModel);
            }
        }

        [RelayCommand]
        private void AddMergeBinMap()
        {
            MergeBinMapViewModels.Add(new BinMapViewModelItem(new BinMap()));
        }

        [RelayCommand]
        private void DeleteMergeBinMap()
        {
            if (SelectedMergedBinMapViewModel != null)
            {
                MergeBinMapViewModels.Remove(SelectedMergedBinMapViewModel);
            }
        }

        [RelayCommand]
        private async Task ImportBinFromMegeredTemplateCSVFolder()
        {
            var allTemplatePaths = GetTemplateFiles();
            if (allTemplatePaths == null || allTemplatePaths.Any() == false) return;
            foreach (var path in allTemplatePaths)
            {

                if (File.Exists(path) == false)
                {

                    MessageBox.Show($"模板文件{path}不存在");
                    return;
                }
            }


            var templateCsvRowListTable = await Task.Run(() => allTemplatePaths.Select(s => GetTemplateRowsFromFile(s).ToList()).ToList());

            var binCodes = GetTemplateAllBinCode(templateCsvRowListTable);


            var viewModels = binCodes.Select(s => new BinMapViewModelItem(new BinMap()
            {
                NewBinCode = s
            }));

            MergeBinMapViewModels = new ObservableCollection<BinMapViewModelItem>(viewModels);

        }



        [RelayCommand]
        private void SaveMap()
        {
            _config.BinMapList = BinMapViewModelViewModels.Select(s => s.BinMap).ToList();
            _config.Save();
        }


        [RelayCommand]
        private void SaveMegedMap()
        {
            _config.MergeBinMapList = MergeBinMapViewModels.Select(s => s.BinMap).ToList();
            _config.Save();
        }


        [RelayCommand]
        private void SaveMergeBinMap()
        {
            _config.MergeBinMapList = MergeBinMapViewModels.Select(s => s.BinMap).ToList();
            _config.Save();
        }


        [RelayCommand]
        private void AddBinMapBinMapViewModelItem()
        {
            BinMapViewModelViewModels.Add(new BinMapViewModelItem(new BinMap()));
        }

        void SaveConfig()
        {
            _config.TemplatePath = TemplatePath;
            _config.Save();
        }

        [ObservableProperty]
        private string _templatePath;

        partial void OnTemplatePathChanged(string value)
        {
            ConvertReportCommand.NotifyCanExecuteChanged();
            SaveConfig();
        }

        [ObservableProperty]
        private string _originalReportPath;

        [ObservableProperty]
        private string _exportReportPath;


        partial void OnOriginalReportPathChanged(string value)
        {
            ConvertReportCommand.NotifyCanExecuteChanged();
            _config.OriginalCSVPath = OriginalReportPath;
            _config.Save();
        }

        partial void OnTemplatePathChanged(string? oldValue, string newValue)
        {
            _config.TemplatePath = TemplatePath;
            _config.Save();
            ConvertReportCommand.NotifyCanExecuteChanged();
        }

        partial void OnExportReportPathChanged(string value)
        {
            _config.ExprotFilePath = ExportReportPath;
            _config.Save();
            ConvertReportCommand.NotifyCanExecuteChanged();
        }

        [RelayCommand]
        private void SelectExportReportPath()
        {
            using var dialog = new FolderBrowserDialog();
            dialog.Description = "选择文件夹";
            dialog.ShowNewFolderButton = true; // 允许新建文件夹
            // 设置初始目录（可选）
            dialog.RootFolder = Environment.SpecialFolder.Desktop;
            if (dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
            var selectedPath = dialog.SelectedPath;
            // 使用路径（例如：显示在 TextBox 中）
            ExportReportPath = selectedPath;
        }

        [RelayCommand]
        private void SelectTemplateReport()
        {
            var openFileDialog = new Microsoft.Win32.OpenFileDialog
            {
                Filter = "csv file (*.csv)|*.csv|All Files (*.*)|*.*"
            };
            var result = openFileDialog.ShowDialog();
            if (result == true)
            {
                TemplatePath = openFileDialog.FileName;
            }

        }



        [RelayCommand]
        private async Task ImportBinFromOriginalCSVFile()
        {
            if (File.Exists(OriginalReportPath) == false) return;
            //import data
            var originalCsvRecordList = (await MiniExcel.QueryAsync<OriginalCsvRecord>(_originalReportPath, hasHeader: true))
                .OrderBy(n => (n.Xindex))
                .ThenBy(n => n.Yindex)
                .ToList();

            var binCodes = originalCsvRecordList.Select(s => s.Bin).Distinct().ToList();
            var viewModels = binCodes.Select(s => new BinMapViewModelItem(new BinMap()
            {
                OriginalBinCode = s
            }));

            BinMapViewModelViewModels = new ObservableCollection<BinMapViewModelItem>(viewModels);

        }


        [RelayCommand]
        private void SelectedOriginalReport()
        {
            var openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "csv file (*.csv)|*.csv|All Files (*.*)|*.*";
            var result = openFileDialog.ShowDialog();
            if (result == true)
            {
                OriginalReportPath = openFileDialog.FileName;
            }
        }


        [RelayCommand]
        private async Task BatchConvert()
        {
            try
            {
                //批量导出
                var originalFileDir = Path.GetDirectoryName(OriginalReportPath);

                var allOriginalPaths = Directory.GetFiles(originalFileDir).Where(n => Path.GetExtension(n).Contains("csv", StringComparison.OrdinalIgnoreCase));
                foreach (var allOriginalPath in allOriginalPaths)
                {
                    await Convert(allOriginalPath);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show($"批量转换失败: {e.Message}");
            }

        }

        [RelayCommand(CanExecute = nameof(CanConvertReport))]
        private async Task ConvertReport()
        {
            try
            {
                await Convert(OriginalReportPath);
            }
            catch (Exception e)
            {
                MessageBox.Show($"转换失败: {e.Message}");
            }

        }
        const string ORIGINAL_DATA_TIME_FORMAT = "yyyyMMddHHmmss";
        const string OUTPUT_DATA_TIME_FORMAT = "yyyy/M/d HH:mm:ss";
        public DateTime GetDateTimeByString(string dateTimeString)
        {
            try
            {
                DateTime dateTime = DateTime.ParseExact(dateTimeString, ORIGINAL_DATA_TIME_FORMAT, System.Globalization.CultureInfo.InvariantCulture);
                return dateTime;
            }
            catch (FormatException)
            {
                Console.WriteLine("日期格式不正确");
                return DateTime.Now;
            }

        }


        private async Task Convert(string originalPath)
        {
            //读取原始报表
            var originalFileName = Path.GetFileNameWithoutExtension(originalPath);
            var waferId = originalFileName.Split("_").ElementAtOrDefault(1);

            if (string.IsNullOrEmpty(waferId))
            {
                waferId = originalFileName;
            }

            var timeString = originalFileName.Split("_")?.ElementAtOrDefault(2)?.Split("(")?.ElementAtOrDefault(0) ?? $"{DateTime.Now:yyyyMMddHHmmss}";
            var time = GetDateTimeByString(timeString);
            timeString = time.ToString(OUTPUT_DATA_TIME_FORMAT);

            var deviceNumber = originalFileName.Split("_").ElementAtOrDefault(3);

            var originalCsvRecordList = (await MiniExcel.QueryAsync<OriginalCsvRecord>(originalPath, hasHeader: true).ConfigureAwait(false)).OrderBy(n => (n.Xindex)).ThenBy(n => n.Yindex).ToList();
            if (originalCsvRecordList.Any() == false)
            {
                System.Windows.MessageBox.Show("原始csv中未读取到有效数据");
                return;
            }

            //var dic = originalCsvRecordList.ToDictionary(n => (n.Xindex, n.Yindex), p => p.Bin.Trim());
            //读取模板数据

            var templateCsvRowList = GetTemplateRowsFromFile(TemplatePath).ToList();
            var table = GetTemplateMergedRow(new List<List<string>>() { templateCsvRowList }, out var templateSummaryInfo);
            if (string.IsNullOrEmpty(deviceNumber))
            {
                deviceNumber = templateSummaryInfo.DeviceNumber;
            }

            //保存结果
            //var fileName = $"{templateSummaryInfo.FileID}-{waferId}-{DateTime.Now:yyyyMMddHHmmss}-{templateSummaryInfo.DeviceNumber}.csv"; //Path.GetFileName(originalPath);
            var fileName = $"{waferId}.csv";
            var exportFileName = Path.Combine(ExportReportPath, fileName);
            await WriteToPath(exportFileName, GetExportedRows(table, originalCsvRecordList, new SummaryInfo() { FileName = waferId, FileID = templateSummaryInfo.FileID, DeviceNumber = deviceNumber, TestTime = timeString }));
        }


        bool CanConvertReport()
        {
            return string.IsNullOrEmpty(TemplatePath) == false && string.IsNullOrEmpty(OriginalReportPath) == false && string.IsNullOrEmpty(ExportReportPath) == false;
        }


        IEnumerable<string> GetExportedRows(List<List<string>> templateCsvRowList, List<OriginalCsvRecord> originalCsvRecordList, SummaryInfo summaryInfo)
        {
            var startRow = 0;
            int? headerRowColCount = null;

            //var summaryInfo = new SummaryInfo();

            foreach (var templateRow in templateCsvRowList)
            {
                var colList = templateRow;
                if (colList.Where(n => string.IsNullOrEmpty(n) == false).Count() < 5)
                {
                    startRow++;
                    if (colList.Count >= 2)
                    {
                        if (colList[0].Contains(nameof(SummaryInfo.FileID), StringComparison.OrdinalIgnoreCase))
                        {
                            //summaryInfo.FileID = colList[1];
                            colList[1] = summaryInfo.FileID;
                        }
                        else if (colList[0].Contains(nameof(SummaryInfo.DeviceNumber), StringComparison.OrdinalIgnoreCase))
                        {
                            colList[1] = summaryInfo.DeviceNumber;
                        }
                        else if (colList[0].Contains(nameof(SummaryInfo.FileName), StringComparison.OrdinalIgnoreCase))
                        {
                            colList[1] = summaryInfo.FileName;
                        }
                        else if (colList[0].Contains(nameof(SummaryInfo.TestTime), StringComparison.OrdinalIgnoreCase))
                        {
                            colList[1] = $"\"{summaryInfo.TestTime}\"";
                        }
                    }
                    yield return string.Join(",", templateRow);
                }
                else if (int.TryParse(colList[0], out _) == false || int.TryParse(colList[1], out _) == false)
                {
                    if (headerRowColCount.HasValue == false && colList.Any(n => string.IsNullOrEmpty(n) == false))
                    {
                        headerRowColCount = colList.Count;
                    }
                    startRow++;
                    //header row
                    yield return string.Join(",", templateRow);
                }
                else
                {
                    break;
                }
                //else
                //{
                //    var posXIndex = 42;
                //    var posYIndex = 43;
                //    var dieX = int.Parse(colList[posXIndex]);
                //    var dieY = int.Parse(colList[posYIndex]);

                //    if (dic.TryGetValue((dieX, dieY), out var binCode) == false)
                //    {
                //        continue;
                //    }
                //}

            }
            var xIndex = headerRowColCount.Value - 3;
            var yIndex = headerRowColCount.Value - 2;
            var templateDataRows = templateCsvRowList.Skip(startRow).ToList();

            var templateDataFilteredRows = templateDataRows.Where(n =>
            {
                if (int.TryParse(n[xIndex], out var x) && int.TryParse(n[yIndex], out var y))
                {
                    return true;
                }
                else
                {
                    return false;
                }


            }).ToList();


            var newBinCodeDicByOriginalBinCodeDictionary = _config.BinMapList.Where(n => n.OriginalBinCode != null).ToDictionary(n => n.OriginalBinCode, n => n.NewBinCode);
            var originalCsvRowsByXy = originalCsvRecordList.ToDictionary(n => (n.Xindex, n.Yindex), p => p);
            foreach (var templateDataFilteredRow in templateDataFilteredRows)
            {
                var x = int.Parse(templateDataFilteredRow[xIndex]);
                var y = int.Parse(templateDataFilteredRow[yIndex]);
                if (originalCsvRowsByXy.TryGetValue((x, y), out var originalCsvRecord))
                {
                    var originalBin = originalCsvRecord.Bin;
                    templateDataFilteredRow[1] = newBinCodeDicByOriginalBinCodeDictionary.GetValueOrDefault(originalBin, "NA");
                }
                else
                {
                    //throw new Exception("未找到对应的Blade机台检测的数据")
                    templateDataFilteredRow[1] = "NA";
                }

                yield return string.Join(",", templateDataFilteredRow);
            }

        }






        /// <summary>
        /// 流读取
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        static IEnumerable<string> GetTemplateRowsFromFile(string path)
        {
            return File.ReadLines(path, Encoding.UTF8);
        }

        private async Task WriteToPath(string fileName, IEnumerable<string> rows)
        {
            // 直接创建 StreamWriter（自动处理文件流）
            await using var writer = new StreamWriter(
                fileName,
                append: false,          // false=覆盖，true=追加
                Encoding.UTF8);
            foreach (var row in rows)
            {
                await writer.WriteLineAsync(row);
            }
        }



        [RelayCommand]
        private void SelectMergeTemplatePath()
        {
            using var dialog = new FolderBrowserDialog();
            dialog.Description = "选择文件夹";
            dialog.ShowNewFolderButton = true; // 允许新建文件夹
            // 设置初始目录（可选）
            dialog.RootFolder = Environment.SpecialFolder.Desktop;
            if (dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
            var selectedPath = dialog.SelectedPath;
            // 使用路径（例如：显示在 TextBox 中）
            MergeTemplateFilePath = selectedPath;

        }
        [RelayCommand]
        private void SelectMergeReportFileExportPath()
        {
            using var dialog = new FolderBrowserDialog();
            dialog.Description = "选择文件夹";
            dialog.ShowNewFolderButton = true; // 允许新建文件夹
            // 设置初始目录（可选）
            dialog.RootFolder = Environment.SpecialFolder.Desktop;
            if (dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
            var selectedPath = dialog.SelectedPath;
            // 使用路径（例如：显示在 TextBox 中）
            MergeReportFileExportPath = selectedPath;

        }
        [RelayCommand]
        private void SelectMergeTemplateInputPath()
        {

            // 创建对话框实例
            var openFileDialog = new OpenFileDialog
            {
                Multiselect = true,    // 启用多选
                Title = "选择文件",     // 对话框标题
                Filter = "csv file (*.csv)|*.csv|All Files (*.*)|*.*",
                //InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) // 初始目录
            };



            // 显示对话框并检查结果
            if (openFileDialog.ShowDialog() == false) return;

            foreach (var fileName in openFileDialog.FileNames)
            {
                MergeFileInputFilePath += (Environment.NewLine + fileName);
            }



            //    using var dialog = new FolderBrowserDialog();

            //dialog.Description = "选择文件夹";
            //dialog.ShowNewFolderButton = true; // 允许新建文件夹
            //// 设置初始目录（可选）
            //dialog.RootFolder = Environment.SpecialFolder.Desktop;
            //if (dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
            //var selectedPath = dialog.SelectedPath;
            //// 使用路径（例如：显示在 TextBox 中）
            //MergeFileInputFilePath = selectedPath;

        }
        [RelayCommand]
        private void SelectMergeReportInputFilePath()
        {

            // 创建对话框实例
            var openFileDialog = new OpenFileDialog
            {
                Multiselect = true,    // 启用多选
                Title = "选择文件",     // 对话框标题
                Filter = "csv file (*.csv)|*.csv|All Files (*.*)|*.*",
                //InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) // 初始目录
            };



            // 显示对话框并检查结果
            if (openFileDialog.ShowDialog() == false) return;

            foreach (var fileName in openFileDialog.FileNames)
            {
                MergeReportFilePath += (Environment.NewLine + fileName);
            }

        }
        private List<string> GetTemplateFiles()
        {
            // 1. 分割字符串并去除空项
            var paths = MergeFileInputFilePath.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);

            // 2. 去重（不区分大小写）
            var uniquePaths = paths
                .Select(p => p.Trim()) // 移除首尾空格
                .Where(p => !string.IsNullOrWhiteSpace(p)) // 确保非空
                .Distinct(StringComparer.OrdinalIgnoreCase) // 不区分大小写比较
                .ToList();

            //foreach (var VARIABLE in MergeFileInputFilePath)
            //{

            //}


            //var allPaths=

            //if (Directory.Exists(MergeFileInputFilePath) == false|| uniquePaths.Any()==false)
            //{
            //    MessageBox.Show("模板文件夹不存在");
            //    return;
            //}

            var allTemplatePaths = uniquePaths; /*Directory.GetFiles(MergeFileInputFilePath).Where(n => Path.GetExtension(n).Contains("csv", StringComparison.OrdinalIgnoreCase)).ToList();*/

            if (allTemplatePaths.Any() == false)
            {
                MessageBox.Show("模板文件不存在");

            }
            return allTemplatePaths;
        }

        private List<string> GetReportFiles()
        {
            // 1. 分割字符串并去除空项
            var paths = MergeReportFilePath.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);

            // 2. 去重（不区分大小写）
            var uniquePaths = paths
                .Select(p => p.Trim()) // 移除首尾空格
                .Where(p => !string.IsNullOrWhiteSpace(p)) // 确保非空
                .Distinct(StringComparer.OrdinalIgnoreCase) // 不区分大小写比较
                .ToList();

            //foreach (var VARIABLE in MergeFileInputFilePath)
            //{

            //}


            //var allPaths=

            //if (Directory.Exists(MergeFileInputFilePath) == false|| uniquePaths.Any()==false)
            //{
            //    MessageBox.Show("模板文件夹不存在");
            //    return;
            //}

            var allTemplatePaths = uniquePaths; /*Directory.GetFiles(MergeFileInputFilePath).Where(n => Path.GetExtension(n).Contains("csv", StringComparison.OrdinalIgnoreCase)).ToList();*/

            if (allTemplatePaths.Any() == false)
            {
                MessageBox.Show("模板文件不存在");

            }
            return allTemplatePaths;
        }
        /// <summary>
        /// 将模板csv进行合并
        /// </summary>
        /// <returns></returns>
        [RelayCommand]
        private async Task MergeTemplateCsv()
        {
            var allTemplatePaths = GetTemplateFiles();
            if (allTemplatePaths == null || allTemplatePaths.Any() == false) return;
            foreach (var path in allTemplatePaths)
            {

                if (File.Exists(path) == false)
                {

                    MessageBox.Show($"模板文件{path}不存在");
                    return;
                }
            }

            if (Directory.Exists(MergeTemplateFilePath) == false)
            {
                MessageBox.Show("请选择合并模板的输出路径");
                return;
            }

            try
            {
                var templateCsvRowListTable = await Task.Run(() => allTemplatePaths.Select(s => GetTemplateRowsFromFile(s).ToList()).ToList());
                var mergedRowList = GetTemplateMergedRow(templateCsvRowListTable, out _);
                //输出组合表格
                var fileName = Path.Combine(MergeTemplateFilePath, Path.GetFileName(allTemplatePaths.First()));
                await WriteToPath(fileName, mergedRowList.Select(s => string.Join(",", s)));

            }
            catch (Exception ex)
            {
                MessageBox.Show($"合并模板的输出路径出错，{ex.Message}");
            }


        }
        /// <summary>
        /// 将报表csv进行合并
        /// </summary>
        /// <returns></returns>
        [RelayCommand]
        private async Task MergeReportCsv()
        {
            var allReportPaths = GetReportFiles();
            if (allReportPaths == null || allReportPaths.Any() == false) return;
            foreach (var path in allReportPaths)
            {

                if (File.Exists(path) == false)
                {

                    MessageBox.Show($"模板文件{path}不存在");
                    return;
                }
            }

            if (Directory.Exists(MergeReportFileExportPath) == false)
            {
                MessageBox.Show("请选择合并模板的输出路径");
                return;
            }

            try
            {
                //拿到表格后，先根据表头提取数据 数据格式为recipe名 wafer名 
                List<ReportModel> reportModels = new List<ReportModel>();
                foreach (var item in allReportPaths)
                {
                    ReportModel reportModel = new ReportModel();
                    string fileName = Path.GetFileName(item);

                    int lastIndex = fileName.LastIndexOf('_');
                    int secondLastIndex = fileName.LastIndexOf('_', lastIndex - 1);
                    int thirdLastIndex = fileName.LastIndexOf('_', secondLastIndex - 1);


                    // 提取数据1（倒数第三个到倒数第二个之间）
                    reportModel.WaferName = fileName.Substring(thirdLastIndex + 1, secondLastIndex - thirdLastIndex - 1);

                    // 提取数据2（开头到倒数第三个之前）
                    reportModel.RecipeName = fileName.Substring(0, thirdLastIndex);

                    reportModel.ReportPath = item;
                    reportModels.Add(reportModel);
                }
                //对wafer进行分组 然后循环
                var GroupWafers = reportModels.GroupBy(x => x.WaferName);
                List<ReportMergeTotalModel> TotalModel = new List<ReportMergeTotalModel>();
                int no = 0;
                //先循环wafer层
                foreach (var Waferitem in GroupWafers)
                {
                    //创建字典 记录die坐标及Bin状态
                    Dictionary<string, bool> DieBinDict = new Dictionary<string, bool>();
                    int allDieCount = 0;
                    //再循环文件内容
                    foreach (var Inspectitem in Waferitem)
                    {
                        //读取文件
                        var originalCsvRecordList = (await MiniExcel.QueryAsync<OriginalCsvRecord>(Inspectitem.ReportPath, hasHeader: true))
                                .OrderBy(n => (n.Xindex))
                                .ThenBy(n => n.Yindex)
                                .ToList();

                        if (allDieCount == 0 || allDieCount < originalCsvRecordList.Count())
                        {
                            allDieCount = originalCsvRecordList.Count();
                        }
                        //计算当前良率 OKbin 默认为0
                        var okdie = allDieCount - originalCsvRecordList.Where(w => w.Bin != "0").Count();
                        Inspectitem.Yield = Math.Round((double)okdie * 100 / (double)allDieCount, 4, MidpointRounding.ToZero).ToString() + "%";

                        foreach (var Dieitem in originalCsvRecordList)
                        {
                            string DieXYKey = Dieitem.Xindex.ToString() + "," + Dieitem.Yindex.ToString();

                            bool IsOK = Dieitem.Bin == "0";
                            //判断是否存在于外部记录的字段
                            if (DieBinDict.TryGetValue(DieXYKey, out bool dieisOk))
                            {
                                if (!dieisOk || !IsOK)
                                {
                                    DieBinDict[DieXYKey] = false;
                                }
                            }
                            else
                            {
                                DieBinDict.Add(DieXYKey, IsOK);
                            }
                        }
                    }
                    //计算总良率
                    var allNgdie = DieBinDict.Where(w => w.Value == false).Count();
                    var allokdie = allDieCount - allNgdie;
                    var allyieIdstr = Math.Round((double)allokdie * 100 / (double)allDieCount, 4, MidpointRounding.ToZero).ToString() + "%";

                    //开始写入文件
                    var waferFileBuilder = new StringBuilder();
                    waferFileBuilder.Append("Wafer ID,merge_Time,AOI ALL Die,AOI NG Die,AOI OK Die,AOI Wafer Yield,");
                    foreach (var Inspectitem in Waferitem)
                    {
                        string RecipeNameTitle = Inspectitem.RecipeName + " Yield,";
                        waferFileBuilder.Append($"{RecipeNameTitle}");
                    }
                    waferFileBuilder.AppendLine();
                    waferFileBuilder.Append(Waferitem.Key + "," + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "," + allDieCount + "," + allNgdie + "," + allokdie + "," + allyieIdstr + ",");
                    foreach (var Inspectitem in Waferitem)
                    {
                        waferFileBuilder.Append($"{Inspectitem.Yield},");
                    }
                    waferFileBuilder.AppendLine();

                    waferFileBuilder.AppendLine("Xindex,Yindex,AOI");

                    foreach (var item in DieBinDict)
                    {
                        waferFileBuilder.AppendLine(item.Key + "," + (item.Value ? "OK" : "NG"));
                    }

                    string filename = Waferitem.Key + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".csv";
                    var waferfilePath = Path.Combine(MergeReportFileExportPath, filename);
                    var task1 = File.WriteAllTextAsync(waferfilePath, waferFileBuilder.ToString());
                    await Task.WhenAll(task1);

                    //记录总表数据
                    no++;
                    ReportMergeTotalModel reportMergeTotalModel = new ReportMergeTotalModel();
                    reportMergeTotalModel.No = no;
                    reportMergeTotalModel.WaferName = Waferitem.Key;
                    reportMergeTotalModel.MergerTime = DateTime.Now.ToString("yyyyMMddHHmmss");
                    reportMergeTotalModel.AllDie = allDieCount;
                    reportMergeTotalModel.AllOkDie = allokdie;
                    reportMergeTotalModel.AllNgDie = allNgdie;
                    reportMergeTotalModel.Yield = allyieIdstr;
                    reportMergeTotalModel.recipeModels = new List<ReportMergeRecipeModel>();

                    foreach (var Inspectitem in Waferitem)
                    {
                        reportMergeTotalModel.recipeModels.Add(new ReportMergeRecipeModel() { Recipe = Inspectitem.RecipeName, Yield = Inspectitem.Yield });
                    }
                    TotalModel.Add(reportMergeTotalModel);
                }
                //统计出现了多少配方
                var recipeNames = TotalModel.SelectMany(s => s.recipeModels).Select(s => s.Recipe).Distinct().ToList();
                var totalFileBuilder = new StringBuilder();
                totalFileBuilder.Append("No,Wafer ID,merge_Time,AOI ALL Die,AOI NG Die,AOI OK Die,AOI Wafer Yield,");
                foreach (var item in recipeNames)
                {
                    string RecipeNameTitle = item + " Yield,";
                    totalFileBuilder.Append($"{item},");
                }
                totalFileBuilder.AppendLine();
                foreach (var item in TotalModel)
                {
                    totalFileBuilder.Append(item.No + "," + item.WaferName + "," + item.MergerTime + "," + item.AllDie + "," + item.AllNgDie + "," + item.AllOkDie + "," + item.Yield + ",");
                    foreach (var recipeitem in recipeNames)
                    {
                        var recipemodel = item.recipeModels.Where(w => w.Recipe == recipeitem).FirstOrDefault();
                        if (recipemodel == null)
                        {
                            totalFileBuilder.Append(" ,");
                        }
                        else
                        {
                            totalFileBuilder.Append(recipemodel.Yield + ",");
                        }
                    }
                    totalFileBuilder.AppendLine();
                }
                string totalfilename = "ReportMerge_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".csv";
                var totalfilePath = Path.Combine(MergeReportFileExportPath, totalfilename);
                var task2 = File.WriteAllTextAsync(totalfilePath, totalFileBuilder.ToString());
                await Task.WhenAll(task2);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"合并报表出错，{ex.Message}");
            }


        }
        public class SummaryInfo
        {
            public string FileID { get; set; }
            public string FileName { get; set; }
            public string DeviceNumber { get; set; }
            public string TestTime { get; set; }

        }

        public class ReportModel
        {
            public string RecipeName { get; set; }
            public string WaferName { get; set; }
            public string ReportPath { get; set; }

            public string Yield { get; set; }
        }

        private List<List<string>> GetTemplateMergedRow(List<List<string>> templateCsvRowListTable, out SummaryInfo summaryInfo)
        {
            summaryInfo = new SummaryInfo();
            //var sourceCount = templateCsvRowListTable.Count;
            //if (sourceCount == 1)
            //{
            //    return templateCsvRowListTable.First().Select(s => s.Split(",").ToList()).ToList();
            //}

            var headerRows = new List<List<string>>();
            //var dataRows = new List<List<string>>();
            var rowsByXyDictionary = new Dictionary<(int x, int y), List<string>>();

            var hasHeaderRow = false;
            var xIndex = 0;
            var yIndex = 0;
            var index = 0;
            var blackRow = false;

            var binLevelByNewBinCodeDictionary = _config.MergeBinMapList.Where(n => n.NewBinCode != null).ToDictionary(n => n.NewBinCode, n => n.BinLevel);

            foreach (var templateCsvRowList in templateCsvRowListTable)
            {
                foreach (var templateRow in templateCsvRowList)
                {
                    index++;
                    var colList = templateRow.Split(",").ToList();
                    if (colList.Count <= 2 || int.TryParse(colList[xIndex], out _) == false || int.TryParse(colList[yIndex], out _) == false)
                    {
                        if (index < 30)
                        {
                            if (colList.Count > 0 && colList.All(string.IsNullOrEmpty) == false)
                            {
                                if (colList.Count >= 1)
                                {
                                    headerRows.Add(colList);
                                    if (colList.Count(n => string.IsNullOrEmpty(n) == false) < 5)
                                    {    //summary row
                                        if (colList[0].Contains(nameof(SummaryInfo.FileID), StringComparison.OrdinalIgnoreCase))
                                        {
                                            summaryInfo.FileID = colList[1].Replace("\"", "").Replace("\\", "");
                                        }
                                        else if (colList[0].Contains(nameof(SummaryInfo.DeviceNumber), StringComparison.OrdinalIgnoreCase))
                                        {
                                            summaryInfo.DeviceNumber = colList[1].Replace("\"", "").Replace("\\", "");
                                        }
                                        else if (colList[0].Contains(nameof(SummaryInfo.FileName), StringComparison.OrdinalIgnoreCase))
                                        {
                                            summaryInfo.FileName = colList[1].Replace("\"", "").Replace("\\", "");
                                        }
                                        else if (colList[0].Contains(nameof(SummaryInfo.TestTime), StringComparison.OrdinalIgnoreCase))
                                        {
                                            summaryInfo.TestTime = colList[1].Replace("\"", "").Replace("\\", "");
                                        }
                                    }
                                    else
                                    {
                                        xIndex = colList.Count - 3;
                                        yIndex = colList.Count - 2;
                                    }
                                }
                            }
                            else
                            {
                                headerRows.Add(Enumerable.Repeat("", 60).ToList());//空白行
                            }
                        }
                    }
                    else
                    {
                        //  dataRows.Add(colList);
                        var x = int.Parse(colList[xIndex]);
                        var y = int.Parse(colList[yIndex]);

                        if (rowsByXyDictionary.TryGetValue((x, y), out var exitRow) == false)
                        {
                            rowsByXyDictionary[(x, y)] = colList;
                            continue;
                        }

                        var existBinCode = exitRow[1];
                        if (binLevelByNewBinCodeDictionary.TryGetValue(existBinCode, out var existedBinLevelValue) == false)
                        {
                            rowsByXyDictionary[(x, y)] = colList;
                            continue;
                        }

                        var newBinCode = colList[1];
                        if (binLevelByNewBinCodeDictionary.TryGetValue(newBinCode, out var newBinLevelValue) == false) continue;

                        if (newBinLevelValue <= existedBinLevelValue)
                        {
                            rowsByXyDictionary[(x, y)] = colList;
                        }


                    }
                }
            }


            // var list = headerRows.Concat(dataRows).ToList();
            var dataList = rowsByXyDictionary.OrderBy(n => int.Parse(n.Value[0])).Select(s => s.Value).ToList();

            //for (var i = 0; i < dataList.Count; i++)
            //{
            //    dataList[i][0] = (i + 1).ToString();
            //}

            return headerRows.Concat(dataList).ToList();

        }


        private List<string> GetTemplateAllBinCode(List<List<string>> templateCsvRowListTable)
        {
            var binCodes = new HashSet<string>();
            var xIndex = 0;
            var yIndex = 0;
            var index = 0;

            foreach (var templateCsvRowList in templateCsvRowListTable)
            {
                foreach (var templateRow in templateCsvRowList)
                {
                    index++;
                    var colList = templateRow.Split(",").ToList();
                    if (colList.Count <= 2 || int.TryParse(colList[xIndex], out _) == false || int.TryParse(colList[yIndex], out _) == false)
                    {
                        if (index < 30)
                        {
                            if (colList.Count > 0 && colList.All(string.IsNullOrEmpty) == false)
                            {
                                if (colList.Count >= 1)
                                {
                                    //headerRows.Add(colList);
                                    if (colList.Count(n => string.IsNullOrEmpty(n) == false) < 5)
                                    {    //summary row

                                    }
                                    else
                                    {
                                        xIndex = colList.Count - 3;
                                        yIndex = colList.Count - 2;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        var binCode = colList[1];
                        if (binCodes.Contains(binCode) == false)
                        {
                            binCodes.Add(binCode);
                        }
                    }
                }
            }

            return binCodes.Distinct().ToList();
        }

    }
}
